home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
gfx
/
opal
/
lsidocs.lha
/
Source
/
Loaders
/
Rendition.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-25
|
8KB
|
318 lines
/* Rendition.c by Martin Boyd 25-Apr-93.
*
* An example file loader using the OpalVision LSI interface.
*
* The rendition file format simply consists of a 1024 byte
* header (Described below) followed by 32 bit (RGBA) image data
* compressed using run-length encoding. Each run is encoded as
* 6 bytes:
*
* Byte 0 - Red
* Byte 1 - Green
* Byte 2 - Blue
* Byte 3 - Alpha
* Byte 4 - Run length low byte
* Byte 5 - Run length high byte
*
* NOTE: This loader only loads the 6RN format as described
* above.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <opal/loadsave.h>
#include <opal/opalpaint.h>
#include <opal/opallib.h>
#include <stdlib.h>
#include <string.h>
char Version[] = "\0$VER: Rendition.Loader 1.0 (25.04.93)";
/* Rendition format information */
struct Tile
{ long Ptr;
long Length;
};
struct RendHeader /* 1024 byte header */
{ long Magic; /* H_MAGIC */
SHORT Version; /* 2 */
char Label[128]; /* ASCII Desciption */
char Date[26]; /* Date of image creation */
SHORT Height; /* Pixel height of image */
SHORT Width; /* Pixel width of image */
SHORT TileHeight; /* Pixel height of tile */
SHORT TileWidth; /* Pixel width of tile */
SHORT Format; /* See below */
SHORT Encoding; /* See below */
long NumRuns; /* Number of runs */
SHORT BlockSize; /* 1024 */
SHORT XOffset; /* Horizontal offset */
SHORT YOffset; /* Vertical offset */
long CMapLen; /* Number of colour table entries */
long CMapPtr; /* Pointer to ColourMap */
char CMapName[64]; /* Colour Map filename */
struct Tile Tile[64]; /* Tile pointer table */
char UnSpec[258]; /* Unspecified (reserved) */
};
#define H_MAGIC 0xE880
#define H_BLOCKSIZE 1024
#define H_HEADERSIZE 1024
/* Format types */
#define H_CRGBAPIX 2 /* 4 bytes per pixel */
#define H_6RUNLH 11 /* 6 bytes per run */
#define H_2RUN 12 /* 2 bytes per run; colour map in seperate file */
#define H_2RUNMAP 13 /* 2 bytes per run; colour map in image file */
#define H_COLOURMAP 20 /* 4 bytes per entry */
#define H_MIPMAP 22 /* Mip map: header, map table and 4-byte pixels */
#define H_ONEDRGBA8 23 /* 1D table of 4-byte pixels */
#define H_ONEDBYTE 24 /* 1D table of bytes */
char LoaderName[] = "Rendition";
char PortName[] = "Rendition_Loader";
int Width,Height; /* Dimension of the image being loaded */
BPTR File; /* File handle of image being loaded */
ULONG LoadFlags; /* Flags from the OVCMD_LOADIMAGE command */
struct MsgPort *LoadPort; /* This modules message port */
struct OpalBase *OpalBase;
BOOL Do_Load (void);
void main (void)
{
struct LSIMessage *Mesg;
struct RendHeader *Header;
LoadPort = CreatePort (PortName,0);
if (LoadPort==NULL)
exit (10);
OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
if (OpalBase==NULL)
{ DeletePort (LoadPort);
exit (10);
}
if (!AddOVLoader (LoaderName,LoadPort,
OVLF_ALLOWIMAGE|OVLF_ALLOWALPHA|OVLF_NEEDFILENAME))
{ DeletePort (LoadPort);
CloseLibrary ((struct Library *)OpalBase);
exit (10);
}
CloseLibrary ((struct Library *)OpalBase); /* library must be closed */
OpalBase = NULL;
while (1)
{ WaitPort (LoadPort);
while (Mesg = (struct LSIMessage *)GetMsg (LoadPort))
{ switch (Mesg->lsi_Type)
{ case OVCMD_LOADIMAGE:
File = Mesg->lsi_File;
LoadFlags = Mesg->lsi_Flags;
ReplyMsg ((struct Message *)Mesg);
Do_Load();
break;
case OVCMD_EXPUNGE:
if (!OpalBase)
OpalBase = (struct OpalBase *)
OpenLibrary ("opal.library",0);
RemOVLoader (LoaderName);
if (OpalBase)
CloseLibrary ((struct Library *)OpalBase);
DeletePort (LoadPort);
ReplyMsg ((struct Message *)Mesg);
exit (0);
break;
case OVCMD_FORMATCHECK:
Header = (struct RendHeader *)Mesg->lsi_Address;
if ((Header->Magic!=H_MAGIC) ||
(Header->Format!=H_6RUNLH))
Mesg->lsi_Result = FALSE;
else
{ Width = Header->Width;
Height = Header->Height;
Mesg->lsi_Result = TRUE;
Mesg->lsi_Width = Width;
Mesg->lsi_Height = Height;
Mesg->lsi_Depth = 24;
Mesg->lsi_Flags = LSIF_HASIMAGE|LSIF_HASALPHA;
}
ReplyMsg ((struct Message *)Mesg);
break;
}
}
}
}
BOOL Do_Load (void)
{
int x,y;
struct MsgPort *HostPort;
struct LSIMessage Mesg;
UBYTE *RBuff,*GBuff,*BBuff,*ABuff,*DestBuff,*SrcBuff;
register UBYTE *Src,*R,*G,*B,*A,RData,GData,BData,AData;
long SBuffSize,DBuffSize,FileLength,RunLength,AmountLeft;
long AmountRead,FilePos;
int DBuffRows,Row;
HostPort = FindPort (OVLOADERPORT); /* Find the host port */
if (HostPort==NULL) return (FALSE);
memset (&Mesg,0,sizeof(struct LSIMessage));
Mesg.lsi_Node.mn_Node.ln_Type = NT_MESSAGE;
Mesg.lsi_Node.mn_ReplyPort = LoadPort;
Mesg.lsi_Node.mn_Length = sizeof (struct LSIMessage);
/* This buffer is used to hold the decompressed data */
DBuffRows = 20;
do
{ DBuffSize = DBuffRows * Width * 4;
DestBuff = AllocMem (DBuffSize,MEMF_CLEAR);
if (DestBuff==NULL)
DBuffRows--;
} while ((DestBuff==NULL) && (DBuffRows>0));
if (DBuffRows==0)
{ Mesg.lsi_Type = OVCMD_ERROR;
Mesg.lsi_Result = LSI_ERR_OUTOFMEM;
LSICmd (HostPort,LoadPort,&Mesg);
return (FALSE);
}
RBuff = DestBuff;
GBuff = DestBuff+(1*DBuffRows*Width);
BBuff = DestBuff+(2*DBuffRows*Width);
ABuff = DestBuff+(3*DBuffRows*Width);
/* Allocate a buffer for raw file data.
* Allocate the biggest buffer we can, start
* with the size of the file and work our way down.
*/
Seek (File,0,OFFSET_END);
FileLength = Seek (File,sizeof(struct RendHeader),OFFSET_BEGINNING);
SBuffSize = FileLength - sizeof (struct RendHeader);
do
{ SrcBuff = AllocMem (SBuffSize,MEMF_CLEAR);
if (SrcBuff==NULL)
SBuffSize = SBuffSize/2;
}
while ((SrcBuff==NULL) && (SBuffSize>(DBuffSize+1024)));
if (SrcBuff==NULL)
{ FreeMem (DestBuff,DBuffSize);
Mesg.lsi_Type = OVCMD_ERROR;
Mesg.lsi_Result = LSI_ERR_OUTOFMEM;
LSICmd (HostPort,LoadPort,&Mesg);
return (FALSE);
}
/* Read in Image data and get the first run */
FilePos = Seek (File,0,OFFSET_CURRENT);
AmountRead = Read (File,SrcBuff,SBuffSize);
AmountLeft = AmountRead;
R = RBuff;
G = GBuff;
B = BBuff;
A = ABuff;
Src = SrcBuff;
RData = *Src++;
GData = *Src++;
BData = *Src++;
AData = *Src++;
RunLength = *Src++;
RunLength += (*Src++)<<8;
Row = 0;
AmountLeft -=6;
for (y=0; y<Height; y++)
{ for (x=0; x<Width;x++)
{ if (RunLength==0)
{ if ((AmountLeft<6) && (FilePos+AmountRead<FileLength))
{ FilePos += AmountRead-AmountLeft;
Seek (File,FilePos,OFFSET_BEGINNING);
AmountRead = Read (File,SrcBuff,SBuffSize);
AmountLeft = AmountRead;
Src = SrcBuff;
}
RData = *Src++;
GData = *Src++;
BData = *Src++;
AData = *Src++;
RunLength = *Src++;
RunLength += (*Src++)<<8;
AmountLeft -= 6;
}
*R++ = RData;
*G++ = GData;
*B++ = BData;
*A++ = AData;
RunLength--;
}
Row++;
/* Once decompress buffer is full, send
* image data to host.
*/
if ((Row==DBuffRows) || (y==Height-1))
{ Mesg.lsi_Planes[0] = RBuff;
Mesg.lsi_Planes[1] = GBuff;
Mesg.lsi_Planes[2] = BBuff;
Mesg.lsi_Width = Width;
Mesg.lsi_Height = Row;
Mesg.lsi_X = 0;
Mesg.lsi_Y = y-Row+1;
Mesg.lsi_Type = OVCMD_SENDDATA;
Mesg.lsi_SubType = OVDF_RGB;
LSICmd (HostPort,LoadPort,&Mesg);
/* Send Alpha channel data if requested */
if (LoadFlags & LSIF_ALPHA)
{ Mesg.lsi_Planes[0] = ABuff;
Mesg.lsi_Width = Width;
Mesg.lsi_Height = Row;
Mesg.lsi_X = 0;
Mesg.lsi_Y = y-Row+1;
Mesg.lsi_Type = OVCMD_SENDDATA;
Mesg.lsi_SubType = OVDF_ALPHA;
LSICmd (HostPort,LoadPort,&Mesg);
}
Row = 0;
R = RBuff;
G = GBuff;
B = BBuff;
A = ABuff;
}
if ((y & 0xF)==0)
{ Mesg.lsi_Type = OVCMD_PERCENTAGE;
Mesg.lsi_Address = "Rend ";
Mesg.lsi_Result = (y*100)/Height;
LSICmd (HostPort,LoadPort,&Mesg);
}
}
Mesg.lsi_Type = OVCMD_DONE;
LSICmd (HostPort,LoadPort,&Mesg);
FreeMem (DestBuff,DBuffSize);
FreeMem (SrcBuff,SBuffSize);
return (TRUE);
}